<script>
import { EditorView, basicSetup } from "codemirror";
import { autocompletion, snippet } from "@codemirror/autocomplete";
import { attributePlugin } from "@/components/AttributeWidget";
import { functionPlugin } from "@/components/FunctionWidget";
import { logicalOperatorPlugin } from "@/components/LogicalOperatorWidget";
import { conditionalOperatorPlugin } from "@/components/ConditionalOperatorWidget";
import { functionMock } from "@/components/functionMock";
import { attributeMock } from "@/components/attributeMock";

export default {
  name: "SalaryCalculator",
  data() {
    return {
      editor: null,
      leftTab: "attribute",
      rightTab: "description",
      calculatorValue: [],
      formulaDescription: "",
      // attributeTree: attributeMock,
      attributeProps: {
        children: "Fields",
        label: "Title",
      },
      functionProps: {
        label: "Name",
        children: "children",
      },
      attributeName: "",
      functionName: "",
      hoverFunctionInfo: null,
      checkedFunctionInfo: null,
    };
  },
  computed: {
    attributeTree() {
      return attributeMock.filter((item) =>
        item.Title.includes(this.attributeName)
      );
    },
    functionTree() {
      return functionMock.filter((item) =>
        item.Name.includes(this.functionName)
      );
    },
    functionDetail() {
      return this.hoverFunctionInfo || this.checkedFunctionInfo;
    },
  },
  methods: {
    formatFunctionDetail(str) {
      if (str) {
        return str.replaceAll("&quot;", '"');
      }
    },
    leaveFunctionTreeNode() {
      this.hoverFunctionInfo = null;
    },
    overFunctionTreeNode(node) {
      if (node.level === 1) return;
      this.hoverFunctionInfo = node.data;
    },
    insertQuote() {
      this.insertCalculator('"" ', false);
    },
    clickFunctionNode(data, node) {
      if (node.level === 1) return;
      this.checkedFunctionInfo = node.data;
      const text = `func.${data.Name} `;
      this.insertCalculator(text, true);
    },
    clickAttributeNode(data, node) {
      if (node.level === 1) return;
      const text = `[${node.parent.data.Title}.${data.Title}] `;
      this.insertCalculator(text, false);
    },
    insertCalculator(text, isSnippet) {
      const { viewState } = this.editor;
      const { state } = viewState;
      const [range] = state?.selection?.ranges || [];

      if (isSnippet) {
        snippet(text)(
          {
            state,
            dispatch: this.editor.dispatch,
          },
          {
            label: text,
            detail: text,
          },
          range.from,
          range.to
        );
      } else {
        this.editor.dispatch({
          changes: {
            from: range.from,
            to: range.to,
            insert: text,
          },
          selection: {
            anchor: range.from + text.length,
          },
        });
      }
    },
    clearCalculator() {
      const { viewState } = this.editor;
      const { state } = viewState;

      this.editor.dispatch({
        changes: {
          from: 0,
          to: state.doc.length,
          insert: "",
        },
        selection: {
          anchor: 0,
        },
      });
    },
  },
  mounted() {
    function myCompletions(context) {
      let word = context.matchBefore(/\w*/);
      if (word.from === word.to && !context.explicit) return null;
      return {
        from: word.from,
        options: [
          { label: "match", type: "keyword" },
          { label: "hello", type: "variable", info: "(World)" },
          { label: "magic", type: "text", apply: "⠁⭒*.✩.*⭒⠁", detail: "macro" },
        ],
      };
    }

    this.editor = new EditorView({
      extensions: [
        basicSetup,
        EditorView.lineWrapping,
        autocompletion({ override: [myCompletions] }),
        EditorView.updateListener.of((v) => {
          // this.formulaDescription = v.state.doc.toString();
          // console.log(v.state.doc.toString());
          // console.log(v.state.doc); //监测得到的最新代码
        }),
        attributePlugin,
        logicalOperatorPlugin,
        conditionalOperatorPlugin,
        functionPlugin,
      ],
      parent: document.querySelector(".codemirror"),
    });
  },
};
</script>

<template>
  <div class="container">
    <div class="calculator">
      <div class="left">
        <el-tabs v-model="leftTab" class="leftTab">
          <el-tab-pane label="字段" name="attribute">
            <div class="selector">
              <div class="parent">
                <el-input size="small" v-model="attributeName"></el-input>
                <div class="item-box">
                  <el-tree
                    :highlight-current="false"
                    :expand-on-click-node="false"
                    :data="attributeTree"
                    :props="attributeProps"
                    @node-click="clickAttributeNode"
                  ></el-tree>
                </div>
              </div>
              <div class="sub">
                <el-input size="small"></el-input>
                <div class="item-box">
                  <el-tree :data="[]" :props="attributeProps"></el-tree>
                </div>
              </div>
            </div>
          </el-tab-pane>
          <el-tab-pane label="函数" name="function">
            <div class="selector" style="flex-direction: column">
              <el-input size="small" v-model="functionName"></el-input>
              <div
                style="
                  width: 100%;
                  height: calc(100% - 32px);
                  display: flex;
                  background: #fff;
                "
              >
                <div
                  style="
                    width: 48%;
                    overflow: auto;
                    height: 100%;
                    border-right: 1px solid #e6e8eb;
                    padding: 4px 0;
                  "
                >
                  <el-tree
                    :highlight-current="false"
                    :expand-on-click-node="false"
                    :data="functionTree"
                    :props="functionProps"
                    @node-click="clickFunctionNode"
                  >
                    <span
                      class="custom-tree-node"
                      slot-scope="{ node, data }"
                      @mouseover="overFunctionTreeNode(node)"
                      @mouseleave="leaveFunctionTreeNode"
                    >
                      <span>{{ node.label }}</span>
                    </span>
                  </el-tree>
                </div>
                <div style="width: 52%; height: 100%">
                  <div
                    v-if="functionDetail"
                    style="padding: 8px; overflow: auto"
                  >
                    <div style="font-size: 14px; font-weight: 600">
                      {{ functionDetail.Name }}
                    </div>
                    <div
                      style="
                        font-size: 12px;
                        margin: 8px 0;
                        color: #565e66;
                        line-height: 20px;
                        word-wrap: break-word;
                        word-break: break-all;
                      "
                    >
                      含义：{{ functionDetail.Description }}
                    </div>
                    <el-divider content-position="left">参数</el-divider>
                    <div
                      style="
                        font-size: 12px;
                        margin: 8px 0;
                        color: #565e66;
                        line-height: 20px;
                        white-space: pre-wrap;
                      "
                    >{{ functionDetail.Parameter }}</div>
                    <el-divider content-position="left">示例</el-divider>
                    <div
                      style="
                        padding: 8px 4px;
                        font-size: 12px;
                        color: #565e66;
                        background: #f7f8f9;
                        line-height: 20px;
                      "
                    >
                      {{ formatFunctionDetail(functionDetail.Example) }}
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </el-tab-pane>
        </el-tabs>
      </div>
      <div class="right">
        <div class="toolbar">
          <div class="operator" @click="insertCalculator('如果 ', false)">
            如果
          </div>
          <div class="operator" @click="insertCalculator('那么 ', false)">
            那么
          </div>
          <div class="operator" @click="insertCalculator('否则 ', false)">
            否则
          </div>
          <el-divider direction="vertical"></el-divider>
          <div class="operator" @click="insertCalculator('且 ', false)">且</div>
          <div class="operator" @click="insertCalculator('或 ', false)">或</div>
          <el-divider direction="vertical"></el-divider>
          <div class="operator" @click="insertCalculator('= ', false)">=</div>
          <div class="operator" @click="insertCalculator('≠ ', false)">≠</div>
          <div class="operator" @click="insertCalculator('< ', false)"><</div>
          <div class="operator" @click="insertCalculator('> ', false)">></div>
          <div class="operator" @click="insertCalculator('<= ', false)">≤</div>
          <div class="operator" @click="insertCalculator('>= ', false)">≥</div>
          <div class="operator" @click="insertCalculator('+ ', false)">+</div>
          <div class="operator" @click="insertCalculator('- ', false)">-</div>
          <div class="operator" @click="insertCalculator('× ', false)">×</div>
          <div class="operator" @click="insertCalculator('÷ ', false)">÷</div>
          <el-divider direction="vertical"></el-divider>
          <div class="operator" @click="insertCalculator('() ', false)">
            ( )
          </div>
          <div class="operator" @click="insertQuote">" "</div>
        </div>
        <div class="codemirror"></div>
        <div class="footer">
          <div class="result">
            <el-alert
              style="background: transparent; user-select: none; padding: 8px 0"
              show-icon
              :closable="false"
              title="成功提示的文案"
              type="success"
            ></el-alert>
          </div>
          <div class="buttons">
            <el-button size="small" @click="clearCalculator">清空</el-button>
            <el-button size="small" type="primary">检查</el-button>
          </div>
        </div>
        <div class="tabs">
          <el-tabs v-model="rightTab" class="rightTab">
            <el-tab-pane label="公式说明" name="description">
              <div
                style="
                  overflow: auto;
                  padding: 0 16px;
                  height: calc(200px - 48px);
                "
              >
                <div
                  contenteditable="true"
                  style="
                    outline: none;
                    line-height: 20px;
                    color: #0e1114;
                    overflow: auto;
                    font-size: 13px;
                    white-space: pre-wrap;
                  "
                >
                  {{ formulaDescription }}
                </div>
              </div>
            </el-tab-pane>
            <el-tab-pane label="公式测算" name="estimate">
              <div
                style="
                  overflow: auto;
                  padding: 0 16px;
                  height: calc(200px - 48px);
                "
              ></div>
            </el-tab-pane>
          </el-tabs>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="less">
.custom-tree-node {
  font-size: 14px;
}

/deep/ .el-divider__text {
  padding: 0 4px;
}

/deep/ .el-divider--horizontal {
  margin: 16px 0;
}

/deep/ .el-divider__text.is-left {
  font-size: 12px;
  color: #565e66;
}

/deep/ .el-tree .el-tree-node__content {
  display: block !important;
}

/deep/ .el-tree .el-tree-node__children {
  overflow: visible !important;
}

/deep/ .el-tabs__header {
  margin-bottom: 0;
}

/deep/ .leftTab .el-tabs__item {
  font-size: 16px;
  font-weight: 600;
}

/deep/ .leftTab .el-tabs__nav-wrap::after {
  display: none;
}

/deep/ .rightTab .el-tabs__nav-wrap::after {
  height: 1px;
  background: transparent;
  border-bottom: 1px dashed #e6e8eb;
  bottom: 4px;
}

/deep/ .el-tabs__nav-scroll {
  padding: 4px 16px;
}

.container {
  height: 100vh;
  width: 80vw;
  display: flex;
  justify-content: center;
  align-items: center;

  .calculator {
    width: 100%;
    height: 80vh;
    display: flex;
    column-gap: 16px;
    padding: 8px;

    .left {
      width: 380px;
      height: 100%;
      background: #fafbfc;

      .selector {
        width: 100%;
        padding: 4px;
        display: flex;
        height: calc(80vh - 48px - 16px);

        .parent {
          width: 50%;
          height: 100%;
          background: #ffffff;
          padding: 4px;
          border-right: 1px solid #e6e8eb;
          display: flex;
          flex-direction: column;

          .item-box {
            margin-top: 12px;
            flex: 1;
            overflow: auto;
          }
        }

        .sub {
          width: 50%;
          height: 100%;
          background: #ffffff;
          padding: 4px;
          display: flex;
          flex-direction: column;

          .item-box {
            margin-top: 12px;
            flex: 1;
          }
        }
      }
    }

    .right {
      flex: 1;
      height: 100%;
      border: 1px solid #e6e8eb;

      .toolbar {
        height: 36px;
        border-bottom: 1px solid #e6e8eb;
        width: 100%;
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        padding: 0 8px;
        column-gap: 2px;

        .operator {
          min-width: 24px;
          box-sizing: border-box;
          height: 24px;
          text-align: center;
          line-height: 24px;
          padding: 0 4px;
          font-size: 12px;
          font-weight: 600;
          cursor: pointer;
          user-select: none;
          color: #565e66;
          border-radius: 4px;

          &:hover {
            background: #f3f9ff;
          }
        }
      }

      .codemirror {
        width: 100%;
        height: calc(100% - 36px - 48px - 200px);
        overflow-y: auto;
        padding: 8px;
      }

      .footer {
        height: 48px;
        width: 100%;
        display: flex;
        align-items: center;
        justify-content: flex-end;
        padding: 0 16px;
        column-gap: 24px;
        border-bottom: 1px solid #e6e8eb;

        .result {
          flex: 1;
        }
      }

      .tabs {
        height: 200px;
      }
    }
  }
}
</style>
